package com.examples.springboot.jpa.gui.department;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;

import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.table.TableCellEditor;

import com.examples.springboot.jpa.pojos.DepartmentDto;
import com.examples.springboot.jpa.pojos.EmployeeDto;
import com.examples.springboot.jpa.resources.DepartmentResource;
import com.examples.springboot.jpa.resources.EmployeeResource;

@SuppressWarnings("serial")
public class EmployeeListView extends JPanel implements PropertyChangeListener{
  private final JTable table = new JTable();
  private final EmployeeResource employeeResource;
  private final EmployeeTableModel tableModel;
  private final EmployeeDataLoader loader;
  private JPopupMenu popup;

  public EmployeeListView(EmployeeResource employeeResource,DepartmentResource departmentResource) {super(new GridLayout(1,0));
    tableModel = new EmployeeTableModel(this.employeeResource = employeeResource);
    table.setModel(tableModel);
    table.setDefaultRenderer(DepartmentDto.class, new DepartmentCellRenderer());
    table.setDefaultEditor(DepartmentDto.class, new DepartmentCellEditor(departmentResource,this));
    table.setRowHeight(25);

  //Create the scroll pane and add the table to it.
    add(new JScrollPane(table,
        JScrollPane.VERTICAL_SCROLLBAR_NEVER,
        JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));

    this.loader=new EmployeeDataLoader(employeeResource);
    this.createMenu();

    // Add the right click event.
    table.addMouseListener(new MouseAdapter() {
      @Override
      public void mouseReleased(MouseEvent e) {
        if (e.isPopupTrigger())
            {
                JTable source = (JTable)e.getSource();
                int row = source.rowAtPoint( e.getPoint() );
                int col = source.columnAtPoint( e.getPoint() );

                if(row>-1) {
                if (! source.isRowSelected(row))
                    source.changeSelection(row, col, false, false);

                popup.show(e.getComponent(), e.getX(), e.getY());
                }
            }
      }
    });
  }

  @Override
  public void propertyChange(PropertyChangeEvent evt) {
    if("onDepartmentChanged".equals(evt.getPropertyName()))
    {
      TableCellEditor defaultEditor = table.getDefaultEditor(DepartmentDto.class);
      if(defaultEditor instanceof DepartmentCellEditor)
      {
        long employeeId = (long) tableModel.getValueAt(((DepartmentCellEditor)defaultEditor).getSelectRowNumber(), 0);
        DepartmentDto department = (DepartmentDto) evt.getNewValue();
        employeeResource.updateEmployee(employeeId, department);
      }
    }else if("postInit".equals(evt.getPropertyName()))
    {
      if(this.tableModel.getRowCount()==0)
        loader.execute();
    }
  }

  private void onDelete(ActionEvent e) {
    Component c = (Component)e.getSource();
    JPopupMenu popup = (JPopupMenu) c.getParent();
    JTable table = (JTable) popup.getInvoker();

    int n = JOptionPane.showConfirmDialog(this,
        "Delete "+table.getSelectedRowCount()+" row?", "Detele items",
        JOptionPane.YES_NO_OPTION);
    if (n == JOptionPane.YES_OPTION) {
      for (int row : table.getSelectedRows()) {
        long employeeId = (long) tableModel.getValueAt(row, 0);
        employeeResource.deleteEmployee(employeeId);
        tableModel.loadData();
      }
    } else if (n == JOptionPane.NO_OPTION) {
      // Empty handle.
    }
  }

  private void onDataPrepared(List<EmployeeDto> employees) {
    TableCellEditor defaultEditor = table.getDefaultEditor(DepartmentDto.class);
    if(defaultEditor instanceof DepartmentCellEditor)
    {
      ((DepartmentCellEditor)defaultEditor).loadData();
    }
    this.tableModel.setData(employees);
  }

  private void createMenu() {
    JMenuItem menu = new JMenuItem("Delete");
    menu.setPreferredSize(new Dimension(80, 25));
    menu.addActionListener(this::onDelete);
    popup = new JPopupMenu();
    popup.add(menu);
  }

  class EmployeeDataLoader extends SwingWorker<List<EmployeeDto>, Void> {
    final EmployeeResource resource;

    public EmployeeDataLoader(EmployeeResource employeeResource) {
      this.resource = employeeResource;
    }

    @Override
    protected List<EmployeeDto> doInBackground() throws Exception {
      return resource.getAll();
    }
    @Override
    protected void done() {
      try {
        List<EmployeeDto> data = get();
        onDataPrepared(data);
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
  }
}
